#include "FPCH.h"

#include "FLoaderFreeType.h"
#include "FMetricsFreeType.h"

namespace Font
{

	LoaderFreeType::LoaderFreeType(Library* a_Library) : Loader(a_Library)
	{
		FT_Init_FreeType(&m_FTLibrary);		
	}
	
	LoaderFreeType::~LoaderFreeType()
	{
		for (std::vector<FontData*>::iterator it = m_FontData.begin(); it != m_FontData.end(); )
		{
			FontData* curr = *it;
			delete [] curr->data;
			delete curr;
			it = m_FontData.erase(it);
		}

		FT_Done_FreeType(m_FTLibrary);
	}

	Face* LoaderFreeType::LoadFace(Family* a_Family, const tb::String& a_Settings)
	{
		FILE* handle = fopen(a_Settings.GetData(), "rb");
		if (!handle) 
		{ 
			LOG_ERROR("Could not open file '%s'.", a_Settings.GetData());
			return NULL; 
		}

		fseek(handle, 0, SEEK_END);
		size_t length = ftell(handle);
		fseek(handle, 0, SEEK_SET);

		FontData* write = new FontData;
		write->data_size = length;
		write->data = new FT_Byte[write->data_size];
		write->face = 0;

		fread(write->data, 1, write->data_size, handle);
		fclose(handle);

		FT_Error error = FT_New_Memory_Face(m_FTLibrary, write->data, write->data_size, 0, &write->face);
		if (error != 0)
		{
			LOG_ERROR("FreeType could not parse '%s'.", a_Settings.GetData());

			delete write;

			return NULL;
		}

		Family* family = m_Library->CreateFamily((const char*)write->face->family_name);

		if (write->face->charmap == NULL)
		{
			FT_Select_Charmap(write->face, FT_ENCODING_UNICODE);
			if (write->face->charmap == NULL)
			{
				LOG_ERROR("Could not parse '%s'.", a_Settings.GetData());
				FT_Done_Face(write->face);

				return NULL;
			}
		}

		Metrics* metrics = new MetricsFreeType(m_Library, this, family, write->face);
		return CreateFace(family, metrics);
	}

	LoaderFreeType::FontData* LoaderFreeType::_CreateFontData(unsigned int a_DataSize)
	{
		FontData* result = new FontData;
		result->data_size = a_DataSize;
		result->data = new FT_Byte[result->data_size];
		result->face = 0;

		m_FontData.push_back(result);

		return result;
	}

	bool LoaderFreeType::LoadDefault()
	{
		return false;
	}

	Metrics* LoaderFreeType::CreateMetrics(Family* a_Family, unsigned int a_Style, CharMap* a_CharMap)
	{
		return new MetricsFreeType(m_Library, this, a_Family, a_Style, a_CharMap);
	}

}; // namespace Font